<template>
  <div class="left">
    <table border="1">
      <tr v-for="(tr,r_i) of  list.slice(4)" :key="r_i">
        <td v-for="(td,d_i) of tr" :key="d_i" :class="td?`check${td}`:''"><span></span></td>
      </tr>
    </table>
  </div>
  <!--  <button type="button"
            @click="()=>{list.forEach((tr,x)=>tr.forEach((td,y)=>list[x][y]=0)); active_xy.length = 0;active_xy.push([0,5]);active_xy.push([1,5]);active_xy.push([2,5]);active_xy.push([3,5]);}">
      I
    </button>
    <button type="button"
            @click="()=>{list.forEach((tr,x)=>tr.forEach((td,y)=>list[x][y]=0)); active_xy.length = 0;active_xy.push([0,5]);active_xy.push([1,5]);active_xy.push([2,5]);active_xy.push([2,6]);}">
      L
    </button>-->
</template>

<script setup>
import {onMounted, onUnmounted, reactive, watch} from "vue";


const list = reactive([
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],

  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]);

const postInfo = defineProps(["now_fk", "state", "speed"]);
const now_fk = postInfo.now_fk;
//变量接收，只是接收到了父组件的初始值，需要跟父组件保持数据的单向流动，就不需要用变量结束。
// const state = postInfo.state;

const active_xy = reactive([]);

const emit = defineEmits(["createNewFk", "gameOver"]);
let autoTimer;
let shape = 0;

const speedObj = {
  "低速": 800,
  "中速": 500,
  "高速": 200
}

watch(now_fk, () => {

  //list.splice(0, 4, ...Array(4).fill(Array(10).fill(0)));
  for (let i = 0; i < 4; i++) {
    for (let j = 0; j < 10; j++) {
      list[i][j] = 0;
    }
  }

  now_fk.forEach((tr, x) => tr.forEach((td, y) => {
    if (td) {
      shape = td;
      active_xy.push([x, y + 3]);
    }
  }));
});

watch(active_xy, () => {
  active_xy.forEach(([x, y]) => {
    list[x][y] = shape;
  });
});

watch(() => postInfo.state, (newValue, oldValue) => {
  if (newValue === 1) {
    if (oldValue < 1) {
      active_xy.length = 0;
      list.forEach((tr, x) => tr.forEach((td, y) => list[x][y] = 0));
    }
    autoRun();
  } else if (oldValue === 1) {
    clearInterval(autoTimer);
  }
});

onMounted(() => {
  window.addEventListener("keydown", handleKeydown);
})

onUnmounted(() => {
  window.removeEventListener("keydown", null);
  clearInterval(autoTimer);
});

watch(() => postInfo.speed, (newValue) => {
  /*if (newValue === "中速") {
    autoRun(500);
  } else if (newValue === "高速") {
    autoRun(200);
  }*/
  autoRun();
})

function autoRun() {
  if (autoTimer) {
    clearInterval(autoTimer);
  }
  autoTimer = setInterval(() => draw(([x, y]) => [x + 1, y]), speedObj[postInfo.speed]);
}

//绘制
function draw(callback) {
  //是否可以移动
  if (active_xy.every(([x0, y0]) => {
    const [x, y] = callback ? callback([x0, y0]) : [x0, y0];
    return x >= 0 && x <= 23 && y >= 0 && y <= 9 && ((list[x] !== undefined && list[x][y] !== undefined && list[x][y] === 0) || active_xy.some(fk => fk.toString() === [x, y].toString()));
  })) {
    active_xy.forEach(([x, y]) => list[x][y] = 0);
    active_xy.forEach(d => [d[0], d[1]] = callback ? callback([d[0], d[1]]) : [d[0], d[1]]);
    //是否停止
  } else if (active_xy.some(([x0, y0]) => {
    const [x, y] = callback ? callback([x0, y0]) : [x0, y0];
    return x > x0 && (x > 23 || (!list[x] || ((!active_xy.some(d => d.toString() === [x, y].toString())) && (list[x][y] !== undefined && list[x][y] > 0))))
  })) {
    //是否游戏已经结束
    if (list.slice(0, 4).some(tr => tr.some(td => td > 0))) {
      emit("gameOver");
    } else {
      let trs = 0;
      for (let i = list.length - 1; i >= 0; i--) {
        if (list[i].every(td => td > 0)) {
          list.splice(i, 1);
          trs++;
        }
      }

      let score = 0;
      if (trs > 0) {
        score = 1 + (trs - 1) * 2;
        //...args 传入不定长参数，args为数组形式  Array(length).fill(元素，开始下标，结束下标),在Vue的相应式对象中，不能替换原对象，否则会导致响应式下标索引失效。Array对象不能用
        //list.unshift(...Array(trs).fill(Array(10).fill(0)));
        for (let k = 0; k < trs; k++) {
          list.unshift([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
        }
      }

      active_xy.length = 0;
      emit("createNewFk", score);
    }
  }
}

function handleKeydown(event) {

  if (postInfo.state === 1) {
    const e = event || window.event;

    const {key, keyCode} = e;

    switch (key) {
      case "ArrowUp":
        let min_x, min_y, max_x, max_y;
        active_xy.forEach(([x0, y0], index) => {
          if (index === 0) {
            min_x = x0;
            min_y = y0;
            max_x = x0;
            max_y = y0;
          } else {
            min_x = min_x < x0 ? min_x : x0;
            min_y = min_y < y0 ? min_y : y0;
            max_x = max_x > x0 ? max_x : x0;
            max_y = max_y > y0 ? max_y : y0;
          }
        });

        let height = max_x - min_x + 1,
            width = max_y - min_y + 1;

        let zc = Math.floor(((height > width ? height : width) - 1) / 2);

        let center_x = min_x + zc, center_y = min_y + zc;

        let pyl = 0;
        if (height > width) {
          if (height - width === 1) {
            if (min_y >= 7) {
              pyl += 10 - min_y - height;
            } else if (min_y !== 0) {
              pyl += width - height;
            }
          } else if (height - width === 3) {
            if (min_y <= 1) {
              pyl += 1 - min_y;
            } else if (min_y >= 8) {
              pyl += 7 - min_y;
            } else {
              pyl += -1;
            }

          }

        }


        let angle = -(Math.PI / 180 * 90);

        if (width !== height) {
          draw(([x, y]) => [
            Math.round((x - center_x) * Math.cos(angle) - (y - center_y) * Math.sin(angle) + center_x),
            Math.round((x - center_x) * Math.sin(angle) + (y - center_y) * Math.cos(angle) + center_y + pyl)
          ]);
        }


        break;
      case "ArrowDown":
        draw(([x, y]) => [x + 1, y]);

        break;
      case "ArrowLeft":
        draw(([x, y]) => [x, y - 1]);

        break;
      case "ArrowRight":
        draw(([x, y]) => [x, y + 1]);
        break;
    }
  }


}

</script>

<style scoped>

.left {
  margin: 0 20px 0 0;
}

/*
table tr:nth-child(-n + 4) {
  opacity: .5;
}
*/

table{
  background-image: radial-gradient(#575776, #2e2e47);
}


table td {
  width: 35px;
  height: 35px;
  text-align: center;
}

</style>